from asyncio import subprocess
import random
import requests
import json
import csv
import time
import logging
from requests.adapters import HTTPAdapter
from urllib3.util.retry import Retry
import urllib.parse
import os
from typing import List

# 设置日志
logging.basicConfig(
    filename="zhongyaocaixiangxi.log",
    level=logging.INFO,
    format="%(asctime)s - %(levelname)s - %(message)s",
)

# 配置请求头
headers = {
    "Accept": "application/json, text/plain, */*",
    "Accept-Encoding": "gzip, deflate",
    "Accept-Language": "zh-CN,zh;q=0.9",
    "Connection": "keep-alive",
    "Content-Type": "application/json;charset=UTF-8",
    "DNT": "1",
    "Host": "www.tcmip.cn:18124",
    "Origin": "http://www.tcmip.cn",
    "Referer": "http://www.tcmip.cn/",
    "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/133.0.0.0 Safari/537.36",
}

# 设置请求重试策略
retry_strategy = Retry(
    total=5,
    backoff_factor=1,
    status_forcelist=[500, 502, 503, 504],
)

adapter = HTTPAdapter(max_retries=retry_strategy)

# 创建请求会话
session = requests.Session()
session.mount("http://", adapter)
session.mount("https://", adapter)

# 目标 CSV 文件
csv_filename = "zhongyaocaixiangxi.csv"

# 初始化 CSV（如果文件不存在，添加表头）
if not os.path.exists(csv_filename):
    with open(csv_filename, mode="w", encoding="utf-8", newline="") as f:
        writer = csv.writer(f)
        writer.writerow(
            [
                "方剂名称",
                "剂型",
                "症状体征/临床表现",
                "处方来源",
                "组成原文",
                "方剂功能主治原文注释",
                "相关中药材列表",
                "具有相似组方中药材的中医古籍方剂列表",
                "具有相似组方化学成分谱的中医古籍方剂列表"
                "具有相似组方中药材的中成药列表",
                "具有相似组方靶标谱的中成药列表",
            ]
        )


# 获取 API 数据
def get_data(interface_url: str):
    try:
        response = session.get(interface_url, headers=headers, timeout=10)
        response.raise_for_status()  # 遇到 HTTP 错误状态码则抛出异常
        return response.json().get("data", [])
    except Exception as e:
        logging.error(f"请求失败: {e}")
        return []


time_g_begin = time.time()

# 读取药材列表
with open("list.csv", mode="r", encoding="utf-8", newline="") as f:
    reader = csv.reader(f)
    for row in reader:
        time_begin = time.time()

        name = row[0]
        url = f"http://www.tcmip.cn:18124/home/detail/?id={urllib.parse.quote(name)}&type=traditional_chinese_medicine_formula&language=cn"

        # 获取数据
        data = get_data(url)

        # 解析基本信息
        herb_info = {
            "方剂名称": name,
            "剂型": "",
            "症状体征/临床表现": "",
            "处方来源": "",
            "组成原文": "",
            "方剂功能主治原文注释": "",
            "相关中药材列表": "",
            "具有相似组方中药材的中医古籍方剂列表": "",
            "具有相似组方中药材的中医古籍方剂列表相似值": "",
            "具有相似组方化学成分谱的中医古籍方剂列表": "",
            "具有相似组方化学成分谱的中医古籍方剂列表相似值": "",
            "具有相似组方中药材的中成药列表": "",
            "具有相似组方中药材的中成药列表相似值": "",
            "具有相似组方化学成分谱的中成药列表": "",
            "具有相似组方化学成分谱的中成药列表相似值": "",
        }

        chinese_patent_drugs = []  # 存放相关中成药数据

        for section in data:
            if section["key"] == "基本信息":
                for item in section["value"]:
                    if item["key"] in herb_info:
                        herb_info[item["key"]] = item["value"]

            elif section["key"] == "相关信息表":
                linkMed: List[str] = []
                for item in section["value"][0]["value"]:
                    linkMed.append(item["中药材名称"][0])
                # print(linkMed)
                herb_info["相关中药材列表"] = ",".join(linkMed)

            elif section["key"] == "相似中医古籍方剂":
                linkedFangJi: List[str] = []
                linkedFangJiNumber: List[str] = []
                if len(section["value"]) > 0:
                    for item in section["value"][0]["value"]:
                        linkedFangJi.append(item[0]["value"])
                        linkedFangJiNumber.append(item[1]["value"])
                    herb_info["具有相似组方中药材的中医古籍方剂列表"] = ",".join(
                        linkedFangJi
                    )
                    herb_info["具有相似组方中药材的中医古籍方剂列表相似值"] = ",".join(
                        linkedFangJiNumber
                    )

                linkedHuaxue: List[str] = []
                linkedHuaxueNumber: List[str] = []
                if len(section["value"]) > 1:
                    for item in section["value"][1]["value"]:
                        linkedHuaxue.append(item[0]["value"])
                        linkedHuaxueNumber.append(item[1]["value"])
                    # print(linkedFangJi, linkedHuaxue)
                    herb_info["具有相似组方化学成分谱的中医古籍方剂列表"] = ",".join(
                        linkedHuaxue
                    )
                    herb_info["具有相似组方化学成分谱的中医古籍方剂列表相似值"] = (
                        ",".join(linkedHuaxueNumber)
                    )

            elif section["key"] == "相似中成药":
                likeHerbList: List[str] = []
                likeHerbNumberList: List[str] = []
                if len(section["value"]) > 0:
                    for item in section["value"][0]["value"]:
                        likeHerbList.append(item[0]["value"])
                        likeHerbNumberList.append(item[1]["value"])
                    herb_info["具有相似组方中药材的中成药列表"] = ",".join(likeHerbList)
                    herb_info["具有相似组方中药材的中成药列表相似值"] = ",".join(
                        likeHerbNumberList
                    )
                likeChemistryList: List[str] = []
                likeChemistryNumberList: List[str] = []
                if len(section["value"]) > 1:
                    for item in section["value"][1]["value"]:
                        likeChemistryList.append(item[0]["value"])
                        likeChemistryNumberList.append(item[1]["value"])
                    herb_info["具有相似组方化学成分谱的中成药列表"] = ",".join(
                        likeChemistryList
                    )
                    herb_info["具有相似组方化学成分谱的中成药列表相似值"] = ",".join(
                        likeChemistryNumberList
                    )
                # print(likeHerbList, likeChemistryList)

        # 将提取的数据写入到 CSV 文件中
        with open(csv_filename, mode="a", encoding="utf-8", newline="") as f:
            writer = csv.writer(f)
            writer.writerow(
                [
                    herb_info["方剂名称"],
                    herb_info["剂型"],
                    herb_info["症状体征/临床表现"],
                    herb_info["处方来源"],
                    herb_info["组成原文"],
                    herb_info["方剂功能主治原文注释"],
                    herb_info["相关中药材列表"],
                    herb_info["具有相似组方中药材的中医古籍方剂列表"],
                    herb_info["具有相似组方中药材的中医古籍方剂列表相似值"],
                    herb_info["具有相似组方化学成分谱的中医古籍方剂列表"],
                    herb_info["具有相似组方化学成分谱的中医古籍方剂列表相似值"],
                    herb_info["具有相似组方中药材的中成药列表"],
                    herb_info["具有相似组方中药材的中成药列表相似值"],
                    herb_info["具有相似组方化学成分谱的中成药列表"],
                    herb_info["具有相似组方化学成分谱的中成药列表相似值"],
                ]
            )

        logging.info(f"已写入: {row[0]}")
        logging.info(f"耗时: {round(time.time() - time_begin):.2f}")
        time.sleep(random.uniform(10, 13))  # 避免触发反爬机制

logging.info("所有数据请求完成！")
try:
    subprocess.run(["pm2", "stop", "1"], check=True)
    logging.info(f"总耗时: {round((time.time()-time_g_begin)/60,3)} min")
    logging.info("pm2 进程 1 已停止。")
except subprocess.CalledProcessError as e:
    logging.error(f"停止 pm2 进程时出错：{e}")
